﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using Core.Logger;

namespace Core
{
	/// <summary>
	/// Xml provider. Saves all the data in Xml files used by BE.
	/// </summary>
    public class ProviderXml : ProviderBase
	{
		public ProviderXml(PostOption option)
		{
		    this.PostOption = option;
		}

	    public override void SavePosts()
	    {
	        try
	        {
	            foreach (PostItem postItem in this.Post.PostItems)
	            {
	                XElement element = new XElement("post");

	                element.Add(
	                    new XElement("author", this.PostOption.AuthorName),
	                    new XElement("title", postItem.Title),
	                    new XElement("description", postItem.Description),
	                    new XElement("content", postItem.Content),
	                    new XElement("ispublished", postItem.IsPublished),
	                    new XElement("isdeleted", "False"),
	                    new XElement("iscommentsenabled", postItem.IsCommentsEnabled),
	                    new XElement("pubDate", postItem.PubDateFormat),
	                    new XElement("lastModified", postItem.PubDateFormat),
	                    new XElement("raters", "0"),
	                    new XElement("rating", "0"),
	                    new XElement("slug", postItem.Slug),
	                    new XElement("tags", this.GetTagsXml(postItem)),
	                    new XElement("comments", GetCommentsXml(postItem)),
	                    new XElement("categories", GetCategoriesXml(postItem)),
	                    new XElement("notifications", String.Empty));
                
	                string fileName = GetFileName("posts", postItem.Id.ToString());
                
	                element.Save(fileName);
	            }
	        }
	        catch (Exception ex)
	        {
	            LoggerInstance.Append(LogStatus.Error, ex.Message);
	        }
	    }

	    private IEnumerable<XElement> GetCategoriesXml(PostItem postItem)
        {
            return postItem.CategoryIdCollection.Select(categId => new XElement("category", categId));
        }

        private IEnumerable<XElement>  GetTagsXml(PostItem postItem)
        {
            return postItem.Tags.Select(tag => new XElement("tag", tag)).ToList();
        }

        private IEnumerable<XElement> GetCommentsXml(PostItem postIem)
        {
            List<XElement> comments = new List<XElement>();
            foreach (CommentItem commentItem in postIem.Comments)
            {
                XElement comment = new XElement("comment");
                comment.Add(new XAttribute("id", commentItem.Id));
                comment.Add(new XAttribute("parentid", commentItem.ParentId));
                comment.Add(new XAttribute("approved", CultureInfo.CurrentCulture.TextInfo.ToTitleCase(commentItem.Approved.ToString())));
                comment.Add(new XAttribute("spam", CultureInfo.CurrentCulture.TextInfo.ToTitleCase(commentItem.Spam.ToString())));
                comment.Add(new XAttribute("deleted", CultureInfo.CurrentCulture.TextInfo.ToTitleCase(commentItem.Deleted.ToString())));
                comment.Add(new XElement("date", commentItem.Date.ToString("u", CultureInfo.InvariantCulture)));
                comment.Add(new XElement("author", commentItem.Author));
                comment.Add(new XElement("email", commentItem.Email));
                comment.Add(new XElement("country", String.Empty));
                comment.Add(new XElement("ip", commentItem.Ip));
                comment.Add(new XElement("content", commentItem.Content));
                comments.Add(comment);
            }
            
            return comments;
        }

	    public override void SaveCategories()
	    {
            if (String.IsNullOrEmpty(this.PostOption.PostAppDataLocation))
            {
                throw new FileNotFoundException("Post file location was not specified");
            }

	        const string CATEGORY_FILE_NAME = "categories.xml";

	        IEnumerable<CategoryItem> elements = this.Post.PostCategory.CategoryItems;
            XElement element = new XElement("categories");
            foreach (CategoryItem el in elements)
            {
                element.Add(new XElement("category",
                    new XAttribute("id", el.Id),
                    new XAttribute("description", el.Description),
                    new XAttribute("parent", el.ParentId),
                    el.Name));
            }

            element.Save(Path.Combine(this.PostOption.PostAppDataLocation, CATEGORY_FILE_NAME));

	    }

		public override void SavePages()
		{
		    try
		    {
		        IEnumerable<PostItem> pages = this.Post.PageItems;

		        foreach (PostItem page in pages)
		        {
		            XElement pageXml = new XElement("page",
		                                            new XElement("title", page.Title),
		                                            new XElement("description", page.Description),
		                                            new XElement("content", page.Content),
		                                            new XElement("keywords", String.Empty),
		                                            new XElement("slug", page.Slug),
		                                            new XElement("parent", Guid.Empty),
		                                            new XElement("isfrontpage", "False"),
		                                            new XElement("showinlist", "True"),
		                                            new XElement("ispublished", "True"),
		                                            new XElement("datecreated", page.PubDateFormat),
		                                            new XElement("datemodified", page.PubDateFormat)
		                );

		            string fileName = this.GetFileName("pages", page.Id.ToString());
		            pageXml.Save(fileName);
		        }
		    }
		    catch (Exception ex)
		    {
                LoggerInstance.Append(LogStatus.Error, ex.Message);
		    }
		}

        /// <summary>
        /// Gets the file name for the post or page.
        /// </summary>
        /// <param name="folderName">posts folder name for post and pages for page item.</param>
        /// <param name="Id">Id of the post or page.</param>
        /// <returns>Returns the file name.</returns>
        private string GetFileName(string folderName, string Id)
        {
            if (String.IsNullOrEmpty(this.PostOption.PostAppDataLocation))
            {
                throw new FileNotFoundException("Post file location was not specified");
            }

            string path = Path.Combine(this.PostOption.PostAppDataLocation, folderName);
            if (!Directory.Exists(path))
            {
               Directory.CreateDirectory(path);
            }

            return Path.Combine(path, Id + ".xml");
        }

	}
}
